
/* GCSx
** SCENE.H
**
** Scenes
** Doesn't include any editor-only functionality
*/

/*****************************************************************************
** Copyright (C) 2003-2006 Janson
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
** 
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
*****************************************************************************/

#ifndef __GCSx_SCENE_H_
#define __GCSx_SCENE_H_

class Scene : virtual public LoadOnly {
protected:
    // Is the scene cached to our file and not in memory?
    int cached;
    FileRead* cacheFile;
    int lockCount;
    int doLock(int play) throw_File;
    int doUnlock(int play);

    // Name of scene, where it's located
    std::string name;
    std::string nameL;
    class World* world;

    // Numeric ID- computer-generated- unique to world- nonzero
    int id;
    
    // Layers
    class Layer* layers[MAX_LAYERS]; // CACHEABLE
    int layerCount;

    // NON-EDITOR, GAMEPLAY DATA (not saved by editor)
    // Viewpoint in pixels (not bounded)
    // positive scrolls left/up (view moves right/down)
    int vpX;
    int vpY;
    
    // Entity lookup by name- this scene only
    EntityMap entitysByName;

    // Entitys in processing order, for this scene only
    EntityOrder entitysByOrder;
    
public:
    // Id must be unique; use ID of 0 if we're going to load anyways
    Scene(class World* myWorld, int myId = 0); // Starts with default settings
    virtual ~Scene();
    
    // Find one of our layers; returns < 0 for not found (expects lowercase name)
    // These are not designed to necessarily be efficient enough for runtime
    int findLayer(const std::string& fName) const;
    int findLayer(const class Layer* fLayer) const;

    // Accessors
    const std::string& getName() const { return name; }
    const std::string& getNameL() const { return nameL; }
    const class World* getWorld() const { return world; }
    class World* getWorld() { return world; }
    int getLayerCount() const { return layerCount; }
    int getId() const { return id; }
    int getBlockType() const { return WorldFileLoad::BLOCKTYPE_SCENE; }
    // (asserts pos is valid)
    // markLock() this scene as long as you're using the layer for nontrivial purposes
    const class Layer* getLayer(int pos) const;
    class Layer* getLayer(int pos);
    
    // File access
    virtual void loadHeader(FileRead* file) throw_File;
    void loadContent(FileRead* file);
    int isContentCached() const;
    void cacheLoad() throw_File;
    // (lock and unlock also recursively affect all layer resources)
    // 'play' versions don't retain source tileset data- only textures
    int markLock() throw_File;
    int markLockPlay() throw_File;
    int markUnlock();
    int markUnlockPlay();
    int isLocked() const;
    
    // GAMEPLAY
    
    // working with entities
    // First places in all indices including world's- call on create/delete
    // Also activates/deactivates if we're locked
    void indexEntity(Entity* addEntity);
    void deindexEntity(Entity* remEntity);
    // Second modifies priority order only- use only when just changing priority
    void orderEntity(Entity* addEntity);
    void deorderEntity(Entity* remEntity);
    // Third modifies name order only- use only when just changing name
    void nameEntity(Entity* addEntity);
    void denameEntity(Entity* remEntity);
    // Since multiple can match, use this for a range
    // Properly handles and optimized for "*" and "string*" wildcards
    // Other wildcard strings will work but you will have to compare
    // each match individually as well. ASSUMES fMatch IS LOWERCASED.
    void matchEntity(const char* fMatch, EntityMap::const_iterator& first, EntityMap::const_iterator& last) const;
    
    // do initial spawning on every layer
    void spawnScene();
    
    // draw current scene (layers, sprites, and all)
    void draw();
    
    // run all entities in order
    void cycle();
    
    // Viewpoint
    int viewX() const { return vpX; }
    int viewY() const { return vpY; }
    void viewX(int newX) { vpX = newX; }
    void viewY(int newY) { vpY = newY; }
};

#endif

